package com.yunwushanhe.document.controller;

import com.yunwushanhe.document.entity.File;
import com.yunwushanhe.document.entity.Users;
import com.yunwushanhe.document.service.impl.FileServiceImpl;
import com.yunwushanhe.document.utils.ChainStack;
import com.yunwushanhe.document.utils.FileUtils;
import com.yunwushanhe.document.utils.PageUtils;
import com.yunwushanhe.document.utils.Unify;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 云雾山河
 * @since 2022-10-24
 */
@Slf4j
@Controller
@RequestMapping("/document/file")
public class FileController {
    @Autowired
    FileServiceImpl fileService;
    @Autowired
    Unify unify;
    @Autowired
    FileUtils fileUtils;

    String userNumberRecord = "";//记录从userController中获取到的userNumber;
    ChainStack<String> stack = new ChainStack<>();//直接用于主页存储进入的路劲
    ChainStack<String> stackTwo = new ChainStack<>();//用于移动和复制过程中存储翻找的路劲（每次使用之后都得清空）

    /**
     * 用于传递 userNumber
     * @param user
     * @return
     */
    @ResponseBody
    @PostMapping("/recordUserNumber")
    public Unify recordUserNumber(Users user){
        String userNumber = user.getUserNumber();
        log.info("================{}=================",userNumber);
        int index = userNumber.indexOf("@");
        fileUtils.setUserNumberRecord(userNumber.substring(0,index));//FileController中一直使用的是这一个对象，所以给他复制后，会改变琪类中的用到这个变量的操作
        this.userNumberRecord = userNumber;
        log.info("================{}=================",fileUtils.getUserNumberRecord());
        return unify;
    }

    /**
     * 新建文件功能
     * @param file
     * @return
     */
    @ResponseBody
    @PostMapping("/add")
    public Unify addFile(@RequestBody File file) {
        boolean folderFlag = fileUtils.createFolder(file.getFilename(), file.getFilePath());
        if(folderFlag){
            file.setFileOfUserNumber(this.userNumberRecord);
            fileService.insert(file);
        }
        unify.setFlag(folderFlag);
        unify.setMessage(unify.isFlag() ? "新建文件成功啦！" : "新建文件失败，该文件名已被使用过不能重复使用！");
        return unify;
    }

    /**
     * 上传文件
     * @param model
     * @param filePath
     * @param files
     * @return
     * @throws IOException
     */
    @PostMapping("/uploadFiles")
    public String uploadFiles(Model model,
                              @RequestParam("filePath")String filePath,
                              @RequestPart("files") MultipartFile[] files) throws IOException {
        log.info("文件上传信息：filePath={},files={}",filePath,files.length);
        boolean upFlag = fileUtils.saveUploadFile(filePath, files);
        if(upFlag && fileUtils.getMessage().isEmpty()){
            ArrayList<FileUtils.Node> fileList = fileUtils.getFileList();
            for (FileUtils.Node node : fileList) {
                File file = new File("文件",node.getName(),node.getPath(),node.getSize(),0);
                file.setFileOfUserNumber(this.userNumberRecord);
                fileService.insert(file);
            }
            model.addAttribute("uploadFileMessage",null);
            fileUtils.setFileList(new ArrayList<>());
            //清空栈
            for (int i = 0; i < stack.getSize(); i++) {
                stack.pop();
            }
            return "success";
        } else {
            model.addAttribute("uploadFileMessage",fileUtils.getMessage());
            fileUtils.setMessage("");//null用isEmpty返回是false,这样设置就是true
            //清空栈
            for (int i = 0; i < stack.getSize(); i++) {
                stack.pop();
            }
            return "fileFunction";
        }
    }

    /**
     * 上传文件夹
     * @param model
     * @param filePath
     * @param folders
     * @return
     * @throws IOException
     */
    @PostMapping("/uploadFolders")
    public String uploadFolders(Model model,
                                @RequestParam("filePath")String filePath,
                                @RequestPart("folders") MultipartFile[] folders) throws IOException {
        log.info("文件夹上传信息：filePath={},folders={}",filePath,folders.length);
        boolean upFlag = fileUtils.saveUploadFolder(filePath, folders);
        //这下面的代码都是为了把文件夹中的关键数据提取出来存储到数据库中
        if(upFlag){
            ArrayList<FileUtils.Node> folderList = fileUtils.getFolderList();
            HashMap<String, HashMap<String, String>> folderMap = fileUtils.getFolderMapTwo();
            Set<String> set = folderMap.keySet();
            //把文件夹中的文件夹放到数据库中
            for (String key : set) {
                HashMap<String, String> innerMap = folderMap.get(key);
                Set<String> innerSet = innerMap.keySet();
                for (String innerKey : innerSet) {
                    String innerValue = innerMap.get(innerKey);
                    File file = new File(innerKey,innerValue);
                    file.setFileOfUserNumber(this.userNumberRecord);
                    fileService.insert(file);
                }
            }
            //把文件夹中的文件放到数据库中
            for (FileUtils.Node node : folderList) {
                File file = new File("文件",node.getName(),node.getPath(),node.getSize(),0);
                file.setFileOfUserNumber(this.userNumberRecord);
                fileService.insert(file);
            }
            model.addAttribute("uploadFolderMessage",null);
            fileUtils.setFolderList(new ArrayList<>());
            fileUtils.setFolderMapTwo(new HashMap<>());
            //清空栈
            for (int i = 0; i < stack.getSize(); i++) {
                stack.pop();
            }
            return "success";
        } else {
            model.addAttribute("uploadFolderMessage",fileUtils.getMessage());
            fileUtils.setMessage("");
            //清空栈
            for (int i = 0; i < stack.getSize(); i++) {
                stack.pop();
            }
            return "fileFunction";
        }
    }

    /**
     * 进入文件夹
     * @param file 获取进入文件夹的路径与其名称
     * @return
     */
    @ResponseBody
    @PostMapping("/openFolder")
    public Unify openFolder(File file){
        List<File> fileList = fileService.select(file.getFilePath(),file.getFilename(),this.userNumberRecord);
        //这行代码主要是用于查询该文件夹下是否有文件，并非分页查询
        stack.push(file.getFilePath());
        log.info("内容={}",file.getFilePath()+file.getFilename()+"/");
        if(fileList.size()==0){
            unify.setFlag(true);
            unify.setMessage("该文件夹中没有文件哦~~~");
        } else {
            unify.setFlag(false);
        }
        return unify;
    }

    /**
     * 进入执行移动和替换翻找过程中的文件
     * @param file
     * @return
     */
    @ResponseBody
    @PostMapping("/openFolderTwo")
    public Unify openFolderTwo(File file){
        List<File> fileList = fileService.select(file.getFilePath(),file.getFilename(),this.userNumberRecord);
        //这行代码主要是用于查询是否有文件，并非分页查询
        stackTwo.push(file.getFilePath());
        log.info("内容={}",file.getFilePath()+file.getFilename()+"/");
        if(fileList.size()==0){
            unify.setFlag(true);
            unify.setMessage("该文件夹中没有文件哦~~~");
        } else {
            unify.setFlag(false);
        }
        return unify;
    }



    /**
     * 返回上一级目录
     * @return
     */
    @ResponseBody
    @GetMapping("/gainRP")
    public Unify returnDirectory(){
        if (stack.getSize()==0){
            unify.setFlag(true);
            unify.setMessage("已是顶端啦！不要再返回了哦~~~");
            unify.setData("/");
        } else {
            unify.setFlag(false);
            unify.setData(stack.pop());
        }
        return unify;
    }

    /**
     * 返回执行移动和替换翻找过程中的目录
     * @return
     */
    @ResponseBody
    @GetMapping("/gainRPTwo")
    public Unify returnDirectoryTwo(){
        if (stackTwo.getSize()==0){
            unify.setFlag(true);
            unify.setMessage("已是顶端啦！不要再返回了哦~~~");
            unify.setData("/");
        } else {
            unify.setFlag(false);
            unify.setData(stackTwo.pop());
        }
        return unify;
    }

    /**
     * 清空 stackTwo 栈
     */
    @ResponseBody
    @GetMapping("/clearStackTwo")
    public Unify clearStackTwo(){
        for (int i = 0; i < stackTwo.getSize(); i++) {
            stackTwo.pop();
        }
        log.info("<--============== {} ==============-->",stackTwo.empty());
        return unify;
    }

    /**
     * 清空 stack 栈
     */
    @ResponseBody
    @GetMapping("/clearStack")
    public Unify clearStack(){
        for (int i = 0; i < stack.getSize(); i++) {
            stack.pop();
        }
        log.info("<--============== {} ==============-->",stack.empty());
        log.info("<--============== -{}- ==============-->",this.userNumberRecord);
        log.info("<--============== --{}-- ==============-->",fileUtils.getUserNumberRecord());
        return unify;
    }

    /**
     * 获取当前重命名文件的原有信息
     * @param id
     * @return
     */
    @ResponseBody
    @GetMapping("/updateFormData/{id}")
    public Unify rename(@PathVariable("id")int id){
        File file = fileService.renameSelect(id);
        if(file==null){
            unify.setFlag(false);
            unify.setMessage("用于重命名的文件信息获取异常！未获取到！");
        }else{
            unify.setFlag(true);
            unify.setData(file);
        }
        return unify;
    }

    /**
     * 正式执行的修改文件名称的操作
     * @param file
     * @return
     */
    @ResponseBody
    @PostMapping("/rename")
    public Unify rename(@RequestBody File file){
        String filePath = file.getFilePath();
        boolean renameResult = fileUtils.rename(filePath + file.getFilename(), filePath + file.getNewFilename());
        if(renameResult){
            unify.setFlag(true);
            unify.setMessage("文件重命名成功啦！");
            fileService.updateFilename(file,this.userNumberRecord);
        }else{
            unify.setFlag(false);
            unify.setMessage("该文件名在同级目录下已被使用过请勿重复使用，文件重命名各式错误！");
        }
        return unify;
    }

    /**
     * 删除文件或者文件夹
     * @param id
     * @return
     */
    @ResponseBody
    @DeleteMapping("/deleteFile/{id}")
    public Unify deleteFile(@PathVariable("id")int id){
        File file = fileService.selectById(id);
        String filename = file.getFilename();
        String filePath = file.getFilePath();
        boolean deleteResult = fileUtils.deleteFile(filename, filePath);
        if(deleteResult){
            fileService.deleteById(id);
            fileService.deleteFolderContentsVague(filePath+filename+"/",this.userNumberRecord);
            unify.setFlag(true);
            unify.setMessage(filename+" 已被删除！");
        } else {
            unify.setFlag(false);
            unify.setMessage("数据记录异常，或是数据路径异常！");
        }
        return unify;
    }

    /**
     * 下载
     * @return
     */
    //@ResponseBody(文件下载功能不能使用这个注解)
    @GetMapping("/download")
    public void download(String filePath, String filename, HttpServletResponse response){
        fileUtils.downloadFile(response, filePath, filename);
    }

    /**
     * 正式执行的移动文件或者文件夹的操作
     * @param removeId
     * @param targetId
     * @return
     */
    @ResponseBody
    @GetMapping("/removeFile/{removeId}/{targetId}")
    public Unify removeFile(
            @PathVariable("removeId")int removeId,
            @PathVariable("targetId")int targetId){
        File removeFile = fileService.selectById(removeId);
        File targetFile = fileService.selectById(targetId);
        String filePath = removeFile.getFilePath()+removeFile.getFilename()+"/";//是文件夹且文件夹里面有内容才会返回值，否则就是null(文件同样如此)
        List<File> fileList = fileService.queryVagueByFilePath(filePath,this.userNumberRecord);
        boolean removeResult = fileUtils.removeFileOrFolder(removeFile, targetFile, fileList);
        if(removeResult){//移动成功
            fileService.copyOrRemoveInsert(removeFile,targetFile,fileList);
            fileService.deleteById(removeId);
            fileService.deleteFolderContentsVague(filePath,this.userNumberRecord);
            unify.setFlag(true);
            unify.setMessage("文件移动成功！");
        }else{
            unify.setFlag(false);
            unify.setMessage("文件移动失败，目标文件夹下已有同名文件，请修改名称后再复制！");
        }
        return unify;
    }

    /**
     * 正式执行的复制文件或者文件夹的操作
     * @param copyId
     * @param targetId
     * @return
     */
    @ResponseBody
    @GetMapping("/copyFile/{copyId}/{targetId}")
    public Unify copyFile(
            @PathVariable("copyId")int copyId,
            @PathVariable("targetId")int targetId){
        File copyFile = fileService.selectById(copyId);
        File targetFile = fileService.selectById(targetId);
        String filePath = copyFile.getFilePath()+copyFile.getFilename()+"/";//是文件夹且文件夹里面有内容才会返回值，否则就是null(文件同样如此)
        List<File> fileList = fileService.queryVagueByFilePath(filePath,this.userNumberRecord);
        boolean copyResult = fileUtils.copyFileOrFolder(copyFile, targetFile, fileList);
        if(copyResult){//复制成功
            fileService.copyOrRemoveInsert(copyFile,targetFile,fileList);
            /*String targetFilePath = targetFile.getFilePath() + targetFile.getFilename() + "/";
            if(copyFile.getFileJudge()!=1){
                copyFile.setFilePath(targetFilePath);
                fileService.insert(copyFile);
            }else{
                if(fileList.isEmpty()){//移动的是空文件夹
                    copyFile.setFilePath(targetFilePath);
                    fileService.insert(copyFile);
                }else{
                    copyFile.setFilePath(targetFilePath);
                    fileService.insert(copyFile);//这里把顶层的copyFile文件的路径改了在增加到数据库中
                    int length = copyFile.getFilePath().length();
                    for (File file : fileList) {//这些都针对copyFile中的子文件或者文件夹的
                        String interceptPath = file.getFilePath().substring(length);
                        file.setFilePath(targetFilePath+interceptPath);
                        fileService.insert(file);
                    }
                }
            }*/
            unify.setFlag(true);
            unify.setMessage("文件复制成功！");
        }else{//复制失败
            unify.setFlag(false);
            unify.setMessage("文件复制失败，目标文件夹下已有同名文件，请修改名称后再复制！");
        }
        return unify;
    }

    /**
     * 覆盖文件所用到的操作
     * @param copyOrRemove
     * @param coverId
     * @param targetId
     * @return
     */
    @ResponseBody
    @GetMapping("/coverFile/{copyOrRemove}/{coverId}/{targetId}")
    public Unify coverFile(
            @PathVariable("copyOrRemove")String copyOrRemove,
            @PathVariable("coverId")int coverId,
            @PathVariable("targetId")int targetId){
        File coverFile = fileService.selectById(coverId);
        File targetFile = fileService.selectById(targetId);
        File deletedFile = fileService.selectByFilePathAndFilename(
                targetFile.getFilePath()+targetFile.getFilename()+"/",
                coverFile.getFilename(),this.userNumberRecord);//找到重名的文件
        if(coverFile.getFilePath().equals(deletedFile.getFilePath())){
            unify.setFlag(true);
            unify.setMessage("文件覆盖成功！");
            return unify;
        }//这个if是为了解决移动或者复制到原来的位置这个需求
        boolean deleteResult = fileUtils.deleteFile(deletedFile.getFilename(), deletedFile.getFilePath());

        if(deleteResult){
            fileService.deleteById(deletedFile.getId());//删除数据库中的数据，这里需要判断是否需要模糊删除是文件夹的情况
            fileService.deleteFolderContentsVague(
                    deletedFile.getFilePath()+deletedFile.getFilename()+"/",this.userNumberRecord);//如果是文件夹则会模糊删除文件夹里面的内容

            String filePath = coverFile.getFilePath()+coverFile.getFilename()+"/";
            List<File> fileList = fileService.queryVagueByFilePath(filePath,this.userNumberRecord);
            if(copyOrRemove.equals("copy")){//这个if里面重新执行复制操作
                boolean copyResult = fileUtils.copyFileOrFolder(coverFile, targetFile, fileList);
                if(copyResult){//复制成功
                    fileService.copyOrRemoveInsert(coverFile,targetFile,fileList);
                    unify.setFlag(true);
                    unify.setMessage("文件复制过程中的覆盖操作成功！");
                }else{//复制失败
                    unify.setFlag(false);
                    unify.setMessage("文件覆盖失败，因为复制文件不成功！");
                }
            } else {//这个里面重新执行移动操作
                boolean removeResult = fileUtils.removeFileOrFolder(coverFile, targetFile, fileList);
                if(removeResult){//移动成功
                    fileService.copyOrRemoveInsert(coverFile,targetFile,fileList);
                    fileService.deleteById(coverId);
                    fileService.deleteFolderContentsVague(filePath,this.userNumberRecord);//模糊删除文件夹里面的内容
                    unify.setFlag(true);
                    unify.setMessage("文件移动成功！");
                }else{
                    unify.setFlag(false);
                    unify.setMessage("文件覆盖失败，因为移动文件不成功！");
                }
            }
        } else {
            unify.setFlag(false);
            unify.setMessage("文件覆盖失败，原文件无法删除！");
        }
        return unify;
    }

    /**
     * 分页查询
     * @param currentPage 当前页数
     * @param pageSize
     * @param file
     * @return
     */
    @ResponseBody
    @GetMapping("{currentPage}/{pageSize}")
    public Unify getPageAll(
            @PathVariable("currentPage") int currentPage,
            @PathVariable("pageSize") int pageSize,
            File file){
        PageUtils page = fileService.getFilePage(currentPage, pageSize, file.getFilePath(), this.userNumberRecord);
        //如果当前页码值大于总页码值，那么重新执行查询操作
//        if(currentPage > page.getPages()){
//            page = fileService.getFilePage(page.getPages(),pageSize,file.getFilePath());
//        }
//        List<File> data = page.getRecords();
//        log.info("总记录数：{}",page.getTotal());
//        log.info("总记录数据：{}",data);
        unify.setFlag(true);
        unify.setData(page);
        return unify;
    }

    /**
     * 用于移动和复制的分页查询
     * @param currentPage
     * @param pageSize
     * @param file
     * @return
     */
    @ResponseBody
    @GetMapping("/subFunction/{currentPage}/{pageSize}")
    public Unify getPageAllTwo(
            @PathVariable("currentPage") int currentPage,
            @PathVariable("pageSize") int pageSize,
            File file){
        PageUtils page = fileService.getFilePageTwo(currentPage, pageSize, file.getFilePath(), this.userNumberRecord);//这里只查文件夹
        unify.setFlag(true);
        unify.setData(page);
        return unify;
    }

    /**
     * 查询操作要调用的功能
     * @param currentPage
     * @param pageSize
     * @param file
     * @return
     */
    @ResponseBody
    @GetMapping("/queryVague/{currentPage}/{pageSize}")
    public Unify getPageQueryVague(
            @PathVariable("currentPage") int currentPage,
            @PathVariable("pageSize") int pageSize,
            File file){
        PageUtils page = fileService.getFilePageVague(currentPage, pageSize, file.getFilename(),this.userNumberRecord);//这里要改，只查文件夹
        unify.setFlag(true);
        unify.setData(page);
        return unify;
    }
}

